#if !defined(_TRACKINGTIPS_H_INCLUDED_)
#define _TRACKINGTIPS_H_INCLUDED_

#pragma once

class CTrackingTips 
{
	enum { TTT_ID = 1234 };

public:
	static HWND GetHwnd()
	{
		return (HWND)CTrackingTips::Instance();
	}

	static BOOL AddTool(HWND hwndTool)
	{
		return CTrackingTips::Instance()._AddTool(hwndTool);
	}

	static void Activate(BOOL bActivate)
	{
		CTrackingTips::Instance()._Activate(bActivate);
	}

	static void Position(int xPos, int yPos)
	{
		CTrackingTips::Instance()._Position(xPos, yPos);
	}

	static void UpdateTipText(LPCTSTR szTipText)
	{
		CTrackingTips::Instance()._UpdateTipText(szTipText);
	}

public:
	~CTrackingTips()
	{
		if(m_hwndTips && ::IsWindow(m_hwndTips))
		{
			if(m_hwndTool)
			{
				TOOLINFO ti;
				::memset(&ti, 0, sizeof(TOOLINFO));
				ti.cbSize = sizeof(TOOLINFO);
				ti.uFlags = TTF_TRACK/* | TTF_ABSOLUTE*/;
				ti.hwnd = m_hwndTool;
				ti.uId = TTT_ID;
				
				::SendMessage(m_hwndTips, TTM_DELTOOL, 0, (LPARAM)&ti);
			}

			::DestroyWindow(m_hwndTips);
		}

		if(m_hFont)
			::DeleteObject(m_hFont);

		if(m_szBufTip)
			delete [] m_szBufTip;
	}

protected:
	static CTrackingTips &Instance()
	{
		static CTrackingTips instance;
		return instance;
	}

	BOOL _AddTool(HWND hwndTool)
	{
		if(m_hwndTool)
		{
			TOOLINFO ti;
			::memset(&ti, 0, sizeof(TOOLINFO));
			ti.cbSize = sizeof(TOOLINFO);
			ti.uFlags = TTF_TRACK/* | TTF_ABSOLUTE*/;
			ti.hwnd = m_hwndTool;
			ti.uId = TTT_ID;
			
			::SendMessage(m_hwndTips, TTM_DELTOOL, 0, (LPARAM)&ti);
		}

		TOOLINFO ti;
		::memset(&ti, 0, sizeof(TOOLINFO));
		ti.cbSize = sizeof(TOOLINFO);
		ti.uFlags = TTF_TRACK/* | TTF_ABSOLUTE*/;
		ti.hwnd = hwndTool;
		ti.uId = TTT_ID;

		BOOL bRet = (BOOL)::SendMessage(m_hwndTips, TTM_ADDTOOL, 0, (LPARAM)&ti);

		if(bRet)
		{
			m_hwndTool = hwndTool;

			if(m_hFont)
				::DeleteObject(m_hFont);
			m_hFont = (HFONT)::SendMessage(m_hwndTool, WM_GETFONT, 0, 0L);
			::SendMessage(m_hwndTips, WM_SETFONT, (WPARAM)m_hFont, (LPARAM)FALSE);
		}

		return bRet;
	}

	void _Activate(BOOL bActivate)
	{
		if(m_hwndTool)
		{
			TOOLINFO ti;
			::memset(&ti, 0, sizeof(TOOLINFO));
			ti.cbSize = sizeof(TOOLINFO);
			ti.uFlags = TTF_TRACK/* | TTF_ABSOLUTE*/;
			ti.hwnd = m_hwndTool;
			ti.uId = TTT_ID;
			
			::SendMessage(m_hwndTips, TTM_TRACKACTIVATE, (WPARAM)(BOOL)bActivate, (LPARAM)&ti);
		}
	}

	void _Position(int xPos, int yPos)
	{
		if(m_hwndTool)
		{
			TOOLINFO ti;
			::memset(&ti, 0, sizeof(TOOLINFO));
			ti.cbSize = sizeof(TOOLINFO);
			ti.uFlags = TTF_TRACK/* | TTF_ABSOLUTE*/;
			ti.hwnd = m_hwndTool;
			ti.uId = TTT_ID;
			
			::SendMessage(m_hwndTips, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD)MAKELONG(xPos, yPos));
		}
	}

	void _UpdateTipText(LPCTSTR szTipText)
	{
		if(m_hwndTool)
		{
			TOOLINFO ti;
			::memset(&ti, 0, sizeof(TOOLINFO));
			ti.cbSize = sizeof(TOOLINFO);
			ti.uFlags = TTF_TRACK/* | TTF_ABSOLUTE*/;
			ti.hwnd = m_hwndTool;
			ti.uId = TTT_ID;

			int nTipText = ::_tcslen(szTipText);
			if(nTipText + 1 > m_nBufTipLen)
			{
				while(nTipText + 1 > m_nBufTipLen)
					m_nBufTipLen += 64;

				delete [] m_szBufTip;
				m_szBufTip = new TCHAR[m_nBufTipLen];
			}

			::_tcscpy(m_szBufTip, szTipText);
			ti.lpszText =  m_szBufTip;
			
			::SendMessage(m_hwndTips, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
		}
	}

	CTrackingTips() : m_hwndTips(NULL), m_hwndTool(NULL), m_szBufTip(NULL), m_hFont(NULL), m_nBufTipLen(0)
	{
		m_hwndTips = ::CreateWindow(TOOLTIPS_CLASS, _T(""),
			WS_POPUP,
			CW_USEDEFAULT, CW_USEDEFAULT,
			CW_USEDEFAULT, CW_USEDEFAULT,
			NULL, (HMENU)NULL, _Module.GetModuleInstance(),
			NULL);
		
//		m_hFont = ::CreateFont(
//			-9,
//			0,
//			0,
//			0,
//			FW_NORMAL,
//			0,
//			0,
//			0,
//			DEFAULT_CHARSET,
//			OUT_DEFAULT_PRECIS,
//			CLIP_DEFAULT_PRECIS,
//			PROOF_QUALITY,
//			VARIABLE_PITCH || FF_SWISS,
//			_T("Arial")/*_T("Verdana")*/);
		::SendMessage(m_hwndTips, WM_SETFONT, (WPARAM)m_hFont, (LPARAM)FALSE);

		::SendMessage(m_hwndTips, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)INT_MAX);
//		::SendMessage(m_hwndTips, TTM_SETTIPBKCOLOR, (WPARAM)::GetSysColor(COLOR_WINDOW), 0);
//		::SendMessage(m_hwndTips, TTM_SETTIPTEXTCOLOR, (WPARAM)::GetSysColor(COLOR_WINDOWTEXT), 0);
	}

	operator HWND () const
	{
		return m_hwndTips;
	}

	HWND GetToolHwnd() const
	{
		return m_hwndTool;
	}

	HWND SetToolHwnd(HWND hwndTool)
	{
		HWND hwndToolPrev = m_hwndTool;
		m_hwndTool = hwndTool;

		return hwndToolPrev;
	}

	CTrackingTips(CTrackingTips &/*rRhs*/) { }
	CTrackingTips &operator = (CTrackingTips &/*rRhs*/) { return *this; }

private:
	LPTSTR m_szBufTip;
	int m_nBufTipLen;

	HWND m_hwndTool;

	HWND m_hwndTips;

	HFONT m_hFont;
};

#endif // !defined(_TRACKINGTIPS_H_INCLUDED_)
